using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using RegionInterface;
using Common;

namespace RegionClient
{
    public delegate void BufferHandle(DataObject data);
    public class ClientSocket
    {
        public event LoginHandle OnConnect;
        public event BufferHandle OnMessage;
        public event Action<Socket> OnDisConnect;
        private void Connect(bool result, string msg)
        {
            if (OnConnect != null) OnConnect(result, msg);
        }
        private void Message(DataObject data)
        {
            if (OnMessage != null) OnMessage(data);
        }
        private void DisConnect(Socket client)
        {
            if (OnDisConnect != null && online) OnDisConnect(client);
        }

        private static string ServerIP = "192.168.0.12";
        private static int ServerPort = 11000;
        private Socket clientSocket = null;
        private IPEndPoint remoteEP = null;
        private bool online = false;

        private int rwOperationCount = 0;
        public ClientSocket(string sIP, int sPort)
        {
            ServerIP = sIP;
            ServerPort = sPort;
            IPAddress ipAddress = IPAddress.Parse(ServerIP);
            remoteEP = new IPEndPoint(ipAddress, ServerPort);
            OnDisConnect = null;
        }
        public void ConnectServer()
        {
            online = false;
            try
            {
                clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
                clientSocket.NoDelay = true;

                StartConnect();
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.ToString());
            }
        }
        //private void StartConnect()
        //{
        //    Thread connectThread = new Thread(delegate()
        //    {
        //        try
        //        {
        //            clientSocket.Connect(remoteEP);
        //            online = true;
        //            StartReceive();
        //            Connect(true, "ok");
        //        }
        //        catch (Exception e)
        //        {
        //            Connect(false, e.ToString());
        //        }
        //    });
        //    connectThread.IsBackground = true;
        //    connectThread.Start();
        //}
        private void StartConnect()
        {
            SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
            connectArgs.RemoteEndPoint = remoteEP;
            connectArgs.Completed += delegate(object sender, SocketAsyncEventArgs e)
            {
                if (e.SocketError == SocketError.Success)
                {
                    online = true;
                    StartReceive();
                    Connect(true, "ok");
                }
                else
                {
                    Connect(false, "can't locate server");
                    online = false;
                }
            };
            clientSocket.ConnectAsync(connectArgs);
        }
        public void CloseAndDispose()
        {
            try
            {
                if (online)
                {
                    online = false;
                    if (clientSocket != null)
                    {
                        //clientSocket.Shutdown(SocketShutdown.Both);
                        clientSocket.Close();
                    }
                }
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.ToString());
            }
            finally
            {
                while (rwOperationCount > 0)            
                    Thread.Sleep(1);
            }
        }
        Thread receiveThread = null;
        private byte[] buffer = new byte[DataObject.BufferSize];
        public BufferPool BufferPool = new BufferPool();
        private int length;
        //private void StartReceive()
        //{
        //    receiveThread = new Thread(delegate()
        //        {
        //            while (online)
        //            {
        //                try
        //                {
        //                    length = clientSocket.Receive(buffer);
        //                    foreach (DataObject obj in BufferPool.BufferToObject(buffer, length))
        //                    {
        //                        Message(obj);
        //                    }
        //                }
        //                catch (Exception e)
        //                {
        //                    DisConnect(clientSocket);
        //                    Log.Debug(e.ToString());
        //                    online = false;
        //                    break;
        //                }
        //            }
        //        });
        //    receiveThread.IsBackground = true;
        //    receiveThread.Start();
        //}
        private void StartReceive()
        {
            SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs();
            receiveArgs.SetBuffer(buffer, 0, buffer.Length);
            receiveArgs.Completed += delegate(object sender, SocketAsyncEventArgs e)
            {
                if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
                {
                    length = e.BytesTransferred;
                    foreach (DataObject obj in BufferPool.BufferToObject(buffer, length))
                    {
                        Message(obj);
                    }
                    clientSocket.ReceiveAsync(receiveArgs);
                }
                else
                {
                    online = false;
                    DisConnect(clientSocket);
                }
            };
            clientSocket.ReceiveAsync(receiveArgs);
        }
        //private void StartReceive()
        //{
        //    clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiveCallBack, null);
        //}
        //private void receiveCallBack(IAsyncResult ar)
        //{
        //    length = clientSocket.EndReceive(ar);
        //    if (length <= 0) return;
        //    try
        //    {
        //        foreach (DataObject obj in BufferPool.BufferToObject(buffer, length))
        //        {
        //            Message(obj);
        //        }
        //        clientSocket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, receiveCallBack, null);
        //    }
        //    catch (Exception ex)//never run here...
        //    {
        //        DisConnect(clientSocket);
        //        online = false;
        //    }
        //}
        public void Send(DataObject data)
        {
            try
            {
                if (online)
                {
                    clientSocket.Send(data.Buffer, 0, data.Length, SocketFlags.None);
                }
            }
            catch (Exception e)
            {
                //DisConnect(clientSocket);
            }
        }
    }
    
}
